package cn.tedu.knows.faq.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
//当前Aop 所有配置都是依赖Spring框架完成的
//所以必须将Aop设置保存到Spring容器
@Component
//下面注解表示当前类不是编写一般业务的
//而是专门编写Aop代码的
@Aspect
public class DemoAspect {
    //定义切面
    //实际还是那个就是用固定的方式指定一个方法
    //方便我们在后面设置在这个方法的之前或之后或发生一次是进行编码
    @Pointcut("execution(public * cn.tedu.knows.faq.controller.TagController.tags(..))")
    // 上面定义的切面下面要写一个方法
    //而这个方法是单纯的一个切面名称的定义,不需要写任何内容
    public void pointCut(){}

    //二.织入内容
    //要先写声明织入哪一个切面中
    // @Before 前置通知,表示方法中的内容会在切面方法运行之前运行
    @Before("pointCut()")
    public void before(JoinPoint joinPoint){
        //在方法运行之前输出内容测试
        //本方法的方法名没有要求
        System.out.println("前置通知执行");
        //方法的参数包含当前切面的各种信息
        //常用的就是切面方法的反射
        //getSignature就是获得方法的信息
        System.out.println(joinPoint.getSignature().getName());
    }

    //后置通知
    @After("pointCut()")
    public void after(){
        System.out.println("后置通知执行");
    }

    //异常通知
    @AfterThrowing("pointCut()")
    public void throwing(){
        System.out.println("方法发生异常");
    }

    //环绕通知
    @Around("pointCut()")
    //环绕通知方法必须有参数,以便执行环绕的目标方法
    //方法还要有返回值,否则原本方法的返回值就无法被调用者接收了
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        //ProceedingJoinPoint 是JoinPoint子接口
        //在原有的基础上添加了放行运行目标方法的功能
        System.out.println("环绕通知,运行之前");
        //利用参数对象,执行目标方法,接受目标方法返回值
        Object object = joinPoint.proceed();
        System.out.println("环绕通知,运行之后");
        return object;
    }
}
